package com.hpsk.shopsatoken.model.user.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hpsk.common.CommonException;
import com.hpsk.common.PageCommon;
import com.hpsk.common.RespResult;
import com.hpsk.common.RespUtils;
import com.hpsk.shopsatoken.model.user.dto.LoginParamDto;
import com.hpsk.shopsatoken.model.user.dto.UserDto;
import com.hpsk.shopsatoken.model.user.entity.User;
import com.hpsk.shopsatoken.model.user.service.IUserService;
import com.hpsk.shopsatoken.model.user.vo.UserVo;
import com.hpsk.utils.ExcelShopUtils;
import com.hpsk.utils.RedisUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;

/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author huangwang
 * @since 2025-05-22
 */
@RestController
@RequestMapping("/user")
@AllArgsConstructor(onConstructor_ = @__(@Autowired))
@Tag(name = "用户控制器",description = "用户相关接口")
@Slf4j
public class UserController {

    private final IUserService userService;
    private final RedisUtils redisUtils;
    @Autowired
    private RedissonClient redissonClient;

    @RequestMapping(value = "/list",method = RequestMethod.GET)
    @Operation(summary = "查询用户列表")
    public RespResult<List<User>> getUserList(){
        return RespUtils.ok(userService.list());
    }

    @RequestMapping(value = "/detail/{id}",method = RequestMethod.GET)
    @Operation(summary = "分页查询用户列表")
    public RespResult<UserVo> detail(@Valid @PathVariable Long id){
        return RespUtils.ok(userService.detail(id));
    }

    @RequestMapping(value = "/getTokenUser",method = RequestMethod.GET)
    @Operation(summary = "token获取用户信息")
    public RespResult<UserVo> getTokenUser(){
        String userId = StpUtil.getLoginIdAsString();
        return RespUtils.ok(userService.detail(Long.valueOf(userId)));
    }

    @RequestMapping(value = "/outLogin",method = RequestMethod.GET)
    @Operation(summary = "退出登录")
    public RespResult<String> outLogin(){
        StpUtil.logout();
        String userId = StpUtil.getLoginIdAsString();
        return RespUtils.ok(userId);
    }

    @RequestMapping(value = "/page",method = RequestMethod.GET)
    @Operation(summary = "分页查询用户列表")
    public RespResult<Page<User>> getUserList(@ParameterObject PageCommon pageCommon){
        return RespUtils.ok(userService.selectPageVo(pageCommon));
    }

    @RequestMapping(value = "/add",method = RequestMethod.POST)
    @Operation(summary = "新增用户",description = "新增")
    public RespResult<User> addUser(@Valid @RequestBody UserDto userDto){
        return RespUtils.ok(userService.add(userDto));
    }

    @GetMapping(value = "/delete")
    @Operation(summary = "删除用户",description = "新增")
    public RespResult<User> delete(@RequestParam(name = "id") Long id){
        return RespUtils.ok(userService.deleteById(id));
    }

    @GetMapping(value = "/getByUserId/{id}")
    @Operation(summary = "根据用户id查询用户信息",description = "根据用户id查询用户信息")
    public RespResult<User> getByUserId(@PathVariable(name = "id") Long id){
        return RespUtils.ok(userService.getById(id));
    }

    @GetMapping(value = "/export")
    @Operation(summary = "导出所有用户",description = "导出所有用户")
    public RespResult<String> export(){
        List<User> list = userService.list();
        ExcelShopUtils.getExcelWriterData(list,"D:\\user.xlsx","用户信息",User.class);
        return RespUtils.ok("");
    }

    @GetMapping(value = "/export2")
    @Operation(summary = "导出所有用户",description = "导出所有用户")
    public RespResult<String> export2(HttpServletRequest request, HttpServletResponse response) throws IOException {
        List<User> list = userService.list();
        ExcelShopUtils.getExcelWriterData(list,response,"用户信息",User.class);
        return RespUtils.ok("");
    }

    @GetMapping(value = "/export3")
    @Operation(summary = "导出所有用户easyExcel",description = "导出所有用户easyExcel")
    public void export3(HttpServletRequest request, HttpServletResponse response) throws IOException {
        List<User> list = userService.list();
        // 这里注意 有同学反应使用swagger 会导致各种问题，请直接用浏览器或者用postman
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        response.setCharacterEncoding("utf-8");
        // 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
        String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
        EasyExcel.write(response.getOutputStream(), User.class).sheet("导出所有用户easyExcel").doWrite(list);
    }

    @GetMapping(value = "/redisTest")
    @Operation(summary = "redis测试",description = "redis测试")
    public RespResult<List<User>> redisTest(){
        String lockKey = "myLock";
        RLock lock = redissonClient.getLock(lockKey);
        try {

            // 尝试加锁，最多等待100秒，上锁后60秒自动解锁
//            boolean isLocked = lock.tryLock(10, 60, TimeUnit.SECONDS);
            boolean isLocked = lock.tryLock();
            log.info("审批节点获取锁->{}", isLocked);
            if (isLocked) {
// 模拟业务逻辑执行5秒钟
                Thread.sleep(12000);

                redisUtils.set("userId",userService.list());

                List<User> users = JSONObject.parseArray(redisUtils.get("userId").toString(), User.class);
                return RespUtils.ok(users);
            } else {

                throw new CommonException("未获取到锁请重试");
            }
        } catch (Exception e) {
            throw new CommonException("未获取到锁请重试");
        } finally {
            // 释放锁
            if (lock != null && lock.isLocked() && lock.isHeldByCurrentThread()) {
                log.info("审批节点释放锁->{}", lock);
                lock.unlock();
            }
        }
    }
    @PostMapping("/login")
    public RespResult<SaTokenInfo> pcLogin(@RequestBody LoginParamDto dto){
        return RespUtils.ok(userService.login(dto));
    }
}
